
use hackit::*;
use super::def::*;

#[cfg(windows)]
pub fn undecorate_symbol(sym: &str, flags: UFlags) -> Option<String> {
    use msvc_demangler::*;

    let mut sym_flags = DemangleFlags::COMPLETE;
    if flags.contains(UFlags::UNDEC_NAME_ONLY) {
        sym_flags = DemangleFlags::NAME_ONLY;
    } else {
        // if flags & UFLAG_UNDEC_TYPE == 0 { sym_flags |= DemangleFlags::NO_ARGUMENTS; }
        if !flags.contains(UFlags::UNDEC_RETN) { sym_flags |= DemangleFlags::NO_FUNCTION_RETURNS; }
    }

    demangle(sym, sym_flags).ok()
}

#[cfg(not(windows))]
pub fn undecorate_symbol(sym: &str, flags: usize) -> Option<String> {
    use cpp_demangle::{Symbol, DemangleOptions};
    Symbol::new(sym).ok().and_then(|s| {
        let mut opts = DemangleOptions::new();
        if flags & UFLAG_UNDEC_TYPE == 0 { opts = opts.no_params(); }
        if flags & UFLAG_UNDEC_RETN == 0 { opts = opts.no_return_type(); }
        s.demangle(&opts).ok()
    })
}

pub fn enum_psinfo() -> Box<dyn Iterator<Item=PsInfo>> {
    use hackit::*;
    use winapi::um::winnt::*;

    Box::new(enum_process().map(|p| {
        let pid = p.pid();
        let mut result = PsInfo {
            pid, name: p.name(),
            window: get_window(pid).map(|w| w.get_text()).unwrap_or(String::new()),
            is_wow64: false,
            path: String::new(),
            cmdline: String::new(),
        };
        Process::open(pid, Some(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)).map(|p| {
            result.is_wow64 = p.is_wow64();
            p.image_path().map(|path| result.path = path);
            p.cmdline().map(|cmd| result.cmdline = cmd);
        });
        result
    }))
}